59  协方差分析

59.1 引言变量关系的度量

协方差(Covariance)和相关系数(Correlation)是衡量两个变量关系的基础统计量。在金融领域,这些指标帮助我们: - 量化风险:投资组合的风险取决于资产间的协方差 - 分散化:选择低相关资产降低组合风险 - 因子识别:发现驱动资产收益的共同因子 - 风险对冲:寻找负相关资产进行对冲

59.2 数学基础

59.2.1 协方差

定义: \[ \text{Cov}(X, Y) = E[(X - \mu_X)(Y - \mu_Y)] \]

样本协方差: \[ \text{Cov}(X, Y) = \frac{1}{n-1}\sum_{i=1}^n (x_i - \bar{x})(y_i - \bar{y}) \]

性质: - \(\text{Cov}(X, X) = \text{Var}(X)\) - \(\text{Cov}(X, Y) = \text{Cov}(Y, X)\) (对称性) - \(\text{Cov}(aX, bY) = ab \cdot \text{Cov}(X, Y)\) (双线性)

59.2.2 相关系数

Pearson相关系数: \[ \rho_{XY} = \frac{\text{Cov}(X, Y)}{\sigma_X \sigma_Y} = \frac{\sum(x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum(x_i - \bar{x})^2}\sqrt{\sum(y_i - \bar{y})^2}} \]

性质: - \(-1 \leq \rho \leq 1\) - \(\rho = 1\):完全正相关 - \(\rho = -1\):完全负相关 - \(\rho = 0\):无线性相关(可能有非线性关系)

59.3 协方差矩阵计算

平台任务1解答代码

以下代码与教学平台任务要求完全一致:

列表 59.1
# 注:sale_points.csv数据文件本地没有,但平台已经内置
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
sale_points-pd.read_csv('sale_points.csv')  # 从CSV文件读取数据
sale points.head()  # 查看sale points前5行数据

平台任务2解答代码

以下代码与教学平台任务要求完全一致:

列表 59.2
# 注:相关分析sales.csv数据文件本地没有,但平台已经内置
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#任务一
import pandas as pd
import matplotlib.pyplot as plt  # 导入Matplotlib绑图库
import numpy as np  # 导入NumPy数值计算库
# 读取数据
data = pd.read_csv('相关分析sales.csv')
# 计算皮尔逊相关系数
corr =
# 计算相关性矩阵
corr_matrix = data.corr()
# 绘制热力图
fig, ax = plt.subplots()
im = ax.imshow(corr_matrix, cmap='YlGnBu')  # 显示热力图矩阵
# 显示相关系数的值
for i in range(corr_matrix.shape[0]):
    for j in range(corr_matrix.shape[1]):  # 遍历range(corr_matrix.shape[1])中的每个j
                text = ax.text(j, i, round(corr_matrix.iloc[i, j],2),  # 按位置索引提取显示相关系数的值
                       ha="center", va="center", color="black")  # 设置标注文本的水平和垂直对齐方式
# 设置坐标轴标签和标题
ax.set_xticks(np.arange(len(corr_matrix.columns)))
ax.set_yticks(np.arange(len(corr_matrix.columns)))  # 设置Y轴刻度标签
ax.set_xticklabels(corr_matrix.columns)  # 设置X轴刻度标签
ax.set_yticklabels(corr_matrix.columns)  # 设置Y轴刻度标签
ax.set_title("Correlation Heatmap")  # 设置图表标题
# 在图形旁添加颜色条
cbar = ax.figure.colorbar(im, ax=ax)
# 显示图形
plt.savefig("热力图.png")
# 输出结果
print('Pearson correlation coefficient: ', corr)
if abs(corr) >= 0.7:  # 条件判断:abs(corr) >= 0.7
    print('存在显著的线性相关性')  # 输出存在显著的线性相关性
else:  # 不满足以上条件时
    print('不存在显著的线性相关性')  # 输出不存在显著的线性相关性
    

#任务二
import numpy as np
from scipy import stats  # 导入SciPy科学计算库
import pandas as pd  # 导入Pandas数据分析库
import statsmodels.api as sm  # 导入统计建模库
import statsmodels.formula.api as smf  # 导入统计建模库
import matplotlib.pyplot as plt  # 导入Matplotlib绑图库
from statsmodels.stats.multicomp import pairwise_tukeyhsd  # 导入统计建模库
from statsmodels.graphics.api import interaction_plot  # 导入统计建模库
from matplotlib.font_manager import FontProperties  # 导入Matplotlib库
myfont=  # 设置中文字体属性
 
# 从CSV文件读取数据存入sale_points
sale_points = pd.read_csv(u'https://huoran.oss-cn-shenzhen.aliyuncs.com/20221116/csv/1592817699758039040.csv',encoding = "gbk")
 
sale_points['market'] = sale_points['market'].astype('category')  # 转换数据类型
# 定义列表sale_points['market'].cat.categories
sale_points['market'].cat.categories=['market 1', 'market 2', 'market 3']
 
sale_points['warranty'] = sale_points['warranty'].astype('category')  # 转换数据类型
# 定义列表sale_points['warranty'].cat.categories
sale_points['warranty'].cat.categories=['1 years', '3 years']
 
print(sale_points.head())  # 输出前几行数据
 
formula = 'sales ~ points + C(market) * C(warranty)'  # 定义模型公式:sales ~ points + C(market) * C(warranty)
sale_points_anova_cov_est = smf.ols(formula, data = sale_points).fit() # dc_sales_est 是一个模型对象
print(sale_points_anova_cov_est.summary())  # 输出合计值
列表 59.3
# =============================================================================
# 题目: 协方差矩阵与相关系数矩阵
# =============================================================================
# 本代码展示如何计算和解释协方差矩阵及相关系数矩阵
# 应用于金融场景:分析多资产收益率之间的关系,为投资组合构建提供基础

# ==================== 导入必要的库 ====================
import pandas as pd  # 数据分析库
import numpy as np  # 数值计算库
import matplotlib.pyplot as plt  # 绘图库
import seaborn as sns  # 统计绘图库

# ==================== 设置中文字体 ====================
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体为黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# ==================== 创建多资产收益率数据 ====================
np.random.seed(42)  # 设置随机种子,确保结果可复现
n_days = 500  # 模拟500个交易日(约2年)

# 定义各资产的期望收益率
mean_returns = [0.001, 0.0008, 0.0012, 0.0005]
# 贵州茅台:0.1%, 五粮液:0.08%, 招商银行:0.12%, 中国平安:0.05%

# ==================== 设定真实的协方差矩阵 ====================
cov_matrix_true = np.array([
    [0.0004, 0.0002, 0.00015, 0.0001],   # 贵州茅台的协方差
    [0.0002, 0.0003, 0.0001, 0.00005],  # 五粮液的协方差
    [0.00015, 0.0001, 0.00035, 0.00008],# 招商银行的协方差
    [0.0001, 0.00005, 0.00008, 0.0002]  # 中国平安的协方差
])
# 对角线元素是各资产的方差,非对角线元素是协方差
# 茅台和五粮液协方差最大(0.0002),因为都是白酒股,高度相关

# ==================== 生成多元正态分布数据 ====================
returns = np.random.multivariate_normal(mean_returns, cov_matrix_true, n_days)
# 根据均值和协方差矩阵生成多元正态分布的收益率数据
# n_days: 生成500个观测值
# 返回形状为(500, 4)的数组,每行代表一天的4个资产收益率

# ==================== 转换为DataFrame ====================
assets = ['贵州茅台', '五粮液', '招商银行', '中国平安']  # 资产名称
df_returns = pd.DataFrame(returns, columns=assets)
# 将NumPy数组转换为DataFrame,列名为资产名称

print('收益率数据(前10行):')  # 打印标题
print(df_returns.head(10))  # 显示前10行数据

# ==================== 计算协方差矩阵 ====================
cov_matrix = df_returns.cov()  # 计算协方差矩阵
# .cov()方法计算每列之间的协方差
# 返回4×4的对称矩阵
print('\n协方差矩阵:')  # 打印标题
print(cov_matrix.round(6))  # 打印协方差矩阵,保留6位小数

# ==================== 计算相关系数矩阵 ====================
corr_matrix = df_returns.corr()  # 计算Pearson相关系数矩阵
# .corr()方法标准化协方差,得到-1到1的相关系数
print('\n相关系数矩阵:')  # 打印标题
print(corr_matrix.round(4))  # 打印相关系数矩阵,保留4位小数

协方差 vs 相关系数:

特性 协方差 相关系数
量纲 有单位(如%²) 无量纲
范围 \((-\infty, +\infty)\) \([-1, 1]\)
标准化
可比性 不同资产对不可比 所有资产对可比
应用 计算组合方差 衡量关系强度

59.4 相关性可视化热力图

列表 59.4
# =============================================================================
# 题目: 相关系数矩阵热力图
# =============================================================================
# 本代码展示如何用热力图可视化相关系数矩阵
# 应用于金融场景:快速识别资产间相关性的强弱模式

# ==================== 绘制热力图 ====================
plt.figure(figsize=(10, 8))  # 创建10×8英寸画布
sns.heatmap(corr_matrix,  # 绘制热力图,输入相关系数矩阵
            annot=True,      # annot=True: 在每个格子中显示数值
            fmt='.2f',       # fmt='.2f': 数值格式,保留2位小数
            cmap='RdYlGn',   # cmap='RdYlGn': 颜色方案,红-黄-绿发散色图
            center=0,        # center=0: 设置颜色中心为0,使正负相关对称
            square=True,     # square=True: 每个格子为正方形
            linewidths=0.5,  # linewidths=0.5: 格子之间的间隔线宽0.5
            cbar_kws={'label': '相关系数'},  # cbar_kws: 颜色条参数,设置标签
            vmin=-1, vmax=1)  # vmin=-1, vmax=1: 设置颜色范围为-1到1

# ==================== 添加标题 ====================
plt.title('资产收益率相关系数矩阵', fontsize=16, fontweight='bold', pad=20)
plt.tight_layout()
plt.show()

# ==================== 找出相关性最高的组合 ====================
# 提取上三角矩阵(排除对角线),避免重复计算
mask = np.triu(np.ones_like(corr_matrix, dtype=bool), k=1)
# np.ones_like: 创建与corr_matrix形状相同的全1矩阵
# np.triu(..., k=1): 提取上三角矩阵,排除对角线(k=1表示从第一条对角线以上开始)
corr_upper = corr_matrix.where(mask)  # 只保留上三角部分,其他置为NaN

# 找最大和最小相关系数
max_corr = corr_upper.max().max()  # 最大相关系数
min_corr = corr_upper.min().min()  # 最小相关系数

max_pair = corr_upper.stack().idxmax()  # 最大相关系数对应的资产对
min_pair = corr_upper.stack().idxmin()  # 最小相关系数对应的资产对
# .stack(): 将DataFrame转换为Series(多级索引)
# .idxmax()/.idxmin(): 找最大/最小值的索引

print(f'最高相关性: {max_pair} = {max_corr:.4f}')  # 打印最相关的资产对
print(f'最低相关性: {min_pair} = {min_corr:.4f}')  # 打印最不相关的资产对

热力图配色方案:

方案 特点 适用场景
RdYlGn 红-黄-绿,中心为0 一般相关性
coolwarm 蓝-白-红,中心为0 科学出版
viridis 紫-黄,感知均匀 色盲友好
RdBu 红-蓝,发散 正负对比明显

59.5 组合风险与协方差

列表 59.5
# =============================================================================
# 题目: 不同权重下的组合风险
# =============================================================================
# 本代码展示如何计算投资组合的风险,并可视化有效前沿
# 应用于金融场景:投资组合优化,寻找最优风险收益平衡

# ==================== 定义资产 ====================
assets_list = ['贵州茅台', '五粮液', '招商银行', '中国平安']  # 资产列表
n_assets = len(assets_list)  # 资产数量

# ==================== 计算年化协方差矩阵 ====================
cov_annual = cov_matrix * 252  # 日数据转年化
# 252是一年的交易日数量
# 日协方差乘以252得到年化协方差

# ==================== 生成不同的权重组合 ====================
np.random.seed(42)  # 设置随机种子
n_portfolios = 1000  # 生成1000个随机组合

weights_list = []  # 存储权重
returns_list = []  # 存储收益率
risks_list = []    # 存储风险

for _ in range(n_portfolios):  # 遍历每个组合
    # 随机生成权重(和为1)
    weights = np.random.random(n_assets)  # 生成4个0-1之间的随机数
    weights = weights / np.sum(weights)  # 归一化,使权重和为1

    # ==================== 组合期望收益 ====================
    portfolio_return = np.sum(df_returns.mean() * weights) * 252
    # 组合收益率 = 各资产收益率的加权平均
    # .mean()计算日收益率,乘以252得到年化收益率

    # ==================== 组合方差(使用矩阵形式) ====================
    portfolio_variance = np.dot(weights.T, np.dot(cov_annual, weights))
    # 组合方差 = w^T * Σ * w
    # np.dot(weights.T, ...): 权重向量的转置
    # np.dot(cov_annual, weights): 协方差矩阵乘以权重向量
    portfolio_std = np.sqrt(portfolio_variance)  # 标准差 = 方差的平方根

    weights_list.append(weights)  # 存储权重
    returns_list.append(portfolio_return)  # 存储收益率
    risks_list.append(portfolio_std)  # 存储风险

# ==================== 转换为DataFrame ====================
df_portfolios = pd.DataFrame({
    '收益率': returns_list,
    '风险(标准差)': risks_list
})

# ==================== 可视化有效前沿 ====================
plt.figure(figsize=(12, 8))  # 创建画布
scatter = plt.scatter(df_portfolios['风险(标准差)'], df_portfolios['收益率'],
                      c=df_portfolios['收益率'] / df_portfolios['风险(标准差)'],
                      # 颜色映射夏普比率 = 收益率/风险
                      cmap='viridis', alpha=0.6, s=50)  # viridis色阶,半透明,点大小50
plt.colorbar(scatter, label='夏普比率')  # 添加颜色条

# ==================== 标记单个资产 ====================
for i, asset in enumerate(assets_list):  # 遍历每个资产
    asset_return = df_returns[asset].mean() * 252  # 计算该资产年化收益率
    asset_risk = np.sqrt(cov_annual.iloc[i, i])  # 计算该资产年化风险
    # cov_annual.iloc[i, i]: 协方差矩阵的对角线元素(方差)
    plt.scatter(asset_risk, asset_return, s=200, marker='*',  # 标记为星号,大小200
                color='red', edgecolors='black', linewidths=1.5)  # 红色,黑色边缘
    plt.text(asset_risk, asset_return, f'  {asset}', fontsize=10)  # 添加资产名称标签

# ==================== 添加标签和标题 ====================
plt.xlabel('年化风险(标准差)', fontsize=12)
plt.ylabel('年化收益率', fontsize=12)
plt.title('投资组合:风险与收益的关系', fontsize=16, fontweight='bold')
plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()

# ==================== 找最优组合(最大夏普比率) ====================
max_sharpe_idx = (df_portfolios['收益率'] / df_portfolios['风险(标准差)']).idxmax()
# 找到夏普比率最大的组合索引
optimal_weights = weights_list[max_sharpe_idx]  # 提取最优权重

print('\n最优组合权重(最大夏普比率):')  # 打印标题
for asset, weight in zip(assets_list, optimal_weights):  # 遍历资产和权重
    print(f'{asset}: {weight:.2%}')  # 打印每个资产的权重,百分比格式

组合风险的数学推导:

对于 \(n\) 个资产的投资组合,权重为 \(w_1, w_2, \ldots, w_n\):

\[ \sigma_p^2 = \sum_{i=1}^n \sum_{j=1}^n w_i w_j \sigma_{ij} \]

矩阵形式: \[ \sigma_p^2 = \mathbf{w}^T \Sigma \mathbf{w} \]

其中: - \(\mathbf{w}\):权重向量 \((n \times 1)\) - \(\Sigma\):协方差矩阵 \((n \times n)\)

分散化原理:

\(\rho_{ij} < 1\) 时: \[ \sigma_p^2 < \sum_{i=1}^n w_i^2 \sigma_i^2 \]

即组合方差小于各资产方差的加权平均,实现风险分散

59.6 时间序列相关性滚动相关

列表 59.6
# =============================================================================
# 题目: 滚动相关系数——相关性时变特征
# =============================================================================
# 本代码展示如何计算滚动相关系数,捕捉相关性的时变特征
# 应用于金融场景:识别市场状态转换,风险对冲时机选择

# ==================== 计算贵州茅台和五粮液的60日滚动相关系数 ====================
window = 60  # 滚动窗口大小:60个交易日(约3个月)
rolling_corr = df_returns['贵州茅台'].rolling(window).corr(df_returns['五粮液'])
# .rolling(60): 创建60个交易日的滚动窗口
# .corr(...): 计算窗口内两个序列的相关系数
# 返回一个Series,长度与原始数据相同

# ==================== 绘制滚动相关系数 ====================
plt.figure(figsize=(14, 6))  # 创建14×6英寸画布
plt.plot(df_returns.index, rolling_corr, linewidth=2, color='#2E86AB')
# 绘制滚动相关系数的时间序列

# ==================== 添加参考线 ====================
plt.axhline(y=0, color='black', linestyle='-', linewidth=0.5)  # y=0水平线
plt.axhline(y=rolling_corr.mean(), color='red', linestyle='--',
            linewidth=2, label=f'均值={rolling_corr.mean():.4f}')
# 均值参考线,红色虚线

# ==================== 填充正负相关区域 ====================
plt.fill_between(df_returns.index, rolling_corr, 0,
                 where=(rolling_corr >= 0), alpha=0.3, color='green', label='正相关期')
# 填充相关系数>0的区域,绿色半透明
plt.fill_between(df_returns.index, rolling_corr, 0,
                 where=(rolling_corr < 0), alpha=0.3, color='red', label='负相关期')
# 填充相关系数<0的区域,红色半透明

# ==================== 添加标题和标签 ====================
plt.title('滚动相关系数(60日窗口)', fontsize=16, fontweight='bold')
plt.xlabel('日期', fontsize=12)
plt.ylabel('相关系数', fontsize=12)
plt.legend(fontsize=11, loc='upper left')  # 显示图例
plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()

# ==================== 相关性稳定性分析 ====================
print(f'相关系数统计:')
print(f'均值: {rolling_corr.mean():.4f}')  # 平均相关系数
print(f'标准差: {rolling_corr.std():.4f}')  # 相关系数的波动性
print(f'最大值: {rolling_corr.max():.4f}')  # 最高相关性
print(f'最小值: {rolling_corr.min():.4f}')  # 最低相关性

# ==================== 识别相关性显著下降的时期 ====================
threshold = rolling_corr.mean() - 2 * rolling_corr.std()
# 阈值 = 均值 - 2倍标准差,低于此值视为异常
low_corr_periods = rolling_corr[rolling_corr < threshold]  # 筛选低相关时期
print(f'\n相关性异常低的时期({len(low_corr_periods)}天):')  # 打印低相关期的天数
print(low_corr_periods.head())  # 显示前几个低相关期

滚动窗口选择: - 短期(20日):捕捉快速变化,噪声大 - 中期(60日):平衡灵敏度和稳定性 - 长期(120日):平滑,识别长期关系

59.7 金融应用行业相关性网络

列表 59.7
# =============================================================================
# 题目: 行业相关性网络可视化
# =============================================================================
# 本代码展示如何分析行业间的相关性结构
# 应用于金融场景:行业轮动策略,板块配置

# ==================== 创建行业数据 ====================
industries_network = ['金融', '科技', '消费', '医药', '能源', '地产']  # 行业列表
n_industries = len(industries_network)  # 行业数量

# ==================== 生成相关行业数据 ====================
# 金融-地产高相关,科技-消费高相关
industry_corr = pd.DataFrame(
    [[1.00, 0.30, 0.35, 0.25, 0.40, 0.60],  # 金融的相关性
     [0.30, 1.00, 0.55, 0.30, 0.25, 0.20],  # 科技的相关性
     [0.35, 0.55, 1.00, 0.35, 0.20, 0.25],  # 消费的相关性
     [0.25, 0.30, 0.35, 1.00, 0.15, 0.20],  # 医药的相关性
     [0.40, 0.25, 0.20, 0.15, 1.00, 0.35],  # 能源的相关性
     [0.60, 0.20, 0.25, 0.20, 0.35, 1.00]], # 地产的相关性
    index=industries_network, columns=industries_network  # 设置行名和列名
)
# 对角线为1(自相关)
# 金融-地产=0.60(高相关,同属周期板块)
# 科技-消费=0.55(高相关,消费升级主题)

print('行业相关系数矩阵:')  # 打印标题
print(industry_corr)  # 打印相关系数矩阵

# ==================== 绘制热力图 ====================
plt.figure(figsize=(10, 8))  # 创建画布
mask = np.triu(np.ones_like(industry_corr, dtype=bool))  # 创建上三角掩码
sns.heatmap(industry_corr,
            annot=True, fmt='.2f',  # 显示数值,保留2位小数
            cmap='RdYlGn', center=0,
            square=True, linewidths=0.5,
            mask=mask,  # 只显示下三角,避免重复
            vmin=-1, vmax=1)
plt.title('行业相关性结构', fontsize=16, fontweight='bold')
plt.tight_layout()
plt.show()

# ==================== 识别高度相关的行业对 ====================
high_corr_pairs = []  # 存储高相关行业对
for i in range(n_industries):  # 遍历所有行业
    for j in range(i+1, n_industries):  # 遍历i之后的所有行业
        corr_val = industry_corr.iloc[i, j]  # 提取相关系数
        if abs(corr_val) > 0.5:  # 如果绝对值>0.5
            high_corr_pairs.append((industries_network[i], industries_network[j], corr_val))
            # 添加到列表

print('\n高度相关行业对(|ρ| > 0.5):')  # 打印标题
for pair in sorted(high_corr_pairs, key=lambda x: abs(x[2]), reverse=True):
    # 按相关系数绝对值降序排列
    print(f'{pair[0]} - {pair[1]}: {pair[2]:.2f}')  # 打印行业对和相关系数

行业轮动策略:

基于相关性的行业轮动: 1. 高相关行业:同涨同跌,避免过度配置 2. 低相关行业:分散化效果好 3. 相关变化:预判板块轮动

59.8 偏相关系数

列表 59.8
# =============================================================================
# 题目: 偏相关系数——控制其他变量的影响
# =============================================================================
# 本代码展示如何计算偏相关系数,剔除第三方变量的影响
# 应用于金融场景:因子分析,识别真实的变量关系

# ==================== 导入必要的库 ====================
from scipy.stats import pearsonr  # 导入Pearson相关系数函数

# ==================== 创建三变量数据 ====================
# X:市场收益率
# Y:个股收益率
# Z:行业因子
np.random.seed(42)  # 设置随机种子
n = 500  # 样本量

market = np.random.normal(0.001, 0.02, n)  # 市场收益率:均值0.1%,标准差2%
industry_factor = np.random.normal(0, 0.01, n)  # 行业因子:均值0,标准差1%
stock = 0.8 * market + 0.5 * industry_factor + np.random.normal(0, 0.015, n)
# 个股收益率 = 0.8×市场 + 0.5×行业因子 + 特质风险

df_partial = pd.DataFrame({  # 创建DataFrame
    '市场': market,
    '个股': stock,
    '行业因子': industry_factor
})

# ==================== 计算简单相关系数 ====================
corr_market_stock = df_partial['市场'].corr(df_partial['个股'])
corr_industry_stock = df_partial['行业因子'].corr(df_partial['个股'])

print('简单相关系数:')
print(f'市场-个股: {corr_market_stock:.4f}')
print(f'行业因子-个股: {corr_industry_stock:.4f}')

# ==================== 计算偏相关系数(控制行业因子) ====================
# 方法1:回归残差法
from sklearn.linear_model import LinearRegression  # 导入线性回归模型

# 个股对行业因子回归
model_stock = LinearRegression().fit(
    df_partial[['行业因子']],  # 自变量:行业因子
    df_partial['个股']  # 因变量:个股收益率
)
residual_stock = df_partial['个股'] - model_stock.predict(df_partial[['行业因子']])
# 残差 = 实际值 - 预测值(剔除行业影响后的个股收益)

# 市场对行业因子回归
model_market = LinearRegression().fit(
    df_partial[['行业因子']],  # 自变量:行业因子
    df_partial['市场']  # 因变量:市场收益率
)
residual_market = df_partial['市场'] - model_market.predict(df_partial[['行业因子']])
# 残差 = 实际值 - 预测值(剔除行业影响后的市场收益)

# ==================== 偏相关系数 = 残差的相关系数 ====================
partial_corr = np.corrcoef(residual_market, residual_stock)[0, 1]
# 计算残差的相关系数,即为偏相关系数

print(f'\n偏相关系数(控制行业因子):')
print(f'市场-个股: {partial_corr:.4f}')
print(f'解释: 剔除行业影响后,市场与个股的真实相关性')

偏相关的含义:

偏相关系数 \(\rho_{XY|Z}\):控制变量 \(Z\) 后,\(X\)\(Y\) 的相关性。

金融应用: - Alpha分离:剔除市场因子后,股票的特质收益 - 因子正交化:构建正交因子 - 归因分析:分离不同来源的影响